<template>
  <div class="picture-edit">
    <el-dialog v-model="showImgEditor" :show-close="false" class="img-editor-dialog" width="1400px" align-center>
      <template #header="{ titleId, titleClass }">
        <div class="my-header">
          <h4 :id="titleId" :class="titleClass">{{ isSingleEdit ? '图片编辑' : '批量图片编辑' }}</h4>
        </div>
      </template>
      <div class="img-editor-container">
        <div class="left-list">
          <div class="left-list-btns" v-if="!isSingleEdit">
            <el-checkbox v-model="leftListChooseAllCheck" size="" class="left-list-choose-all" @change="leftListChooseAll" label="全选" />
            <el-checkbox v-model="leftListChooseBackCheck" size="" class="left-list-choose-back" @change="leftListChooseBack" label="反选" />
          </div>
          <el-scrollbar>
            <ul>
              <li v-for="(img, index) in imgEditorList" :key="img.id" :class="{ activeImg: curImg == index }" @click="changeImg(index, img)">
                <img :src="img.url" alt="" />
                <div v-if="!isSingleEdit">
                  <div class="left-img-index">
                    <span>{{ index + 1 }}</span>
                  </div>
                  <div class="delete" @click.stop="deleteImg(index)">
                    <el-icon>
                      <Close />
                    </el-icon>
                  </div>
                  <div class="left-img-checked" @click.stop>
                    <el-checkbox v-model="img.checked" />
                  </div>
                </div>
              </li>
            </ul>
          </el-scrollbar>
        </div>
        <div class="tool-list">
          <div class="tool-btn" v-for="(tool, index) in toolList" :key="index" :class="{ activeTool: curTool == index }" @click="changeTool(index)">
            <i></i>
            <span>{{ tool.text }}</span>
          </div>
          <div class="tool-btn" @click="showModuleAxupImgs = true">
            <i></i>
            <span>更换图片</span>
          </div>
          <el-select v-model="picPosition" class="m-2" placeholder="选择排布方式" size="small">
            <el-option v-for="item in picPositionOptions" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </div>
        <div class="right-img-box">
          <div class="cropper-container" v-if="curTool == 1">
            <div class="img-container">
              <div class="cropper-img-box">
                <div
                  class="cropper"
                  v-for="(img, index) in imgEditorList"
                  :key="img.id"
                  :style="{
                    opacity: curImg == index ? 1 : 0,
                    zIndex: curImg == index ? 1 : 0
                  }"
                >
                  <vueCropper
                    ref="cropper"
                    :img="img.base64Url"
                    :outputSize="option.size"
                    :outputType="option.outputType"
                    :autoCropWidth="option.autoCropWidth"
                    :fixed-number="option.fixedNumber"
                    :fixed="true"
                    mode="contain"
                    :full="true"
                    :centerBox="true"
                    :autoCrop="true"
                    maxImgSize="100%"
                  ></vueCropper>
                </div>
              </div>
              <div class="reset-btn" @click="resetCrop">
                <el-button size="">撤销</el-button>
              </div>
            </div>
            <div class="bottom-tool-btn">
              <div class="check-btn" @click="checkImg">
                <el-button type="primary" size="">修改</el-button>
              </div>
              <ul>
                <span>比例：</span>
                <li v-for="(item, index) in cropList" :key="index" @click="changeScale(index, item.scale)" :class="{ activeScale: curScale == index }">
                  <div class="icon-box">{{ item.icon }}</div>
                  <div class="tool-name">{{ item.text }}</div>
                </li>
              </ul>
            </div>
          </div>
          <div v-else class="changesize-container">
            <div class="img-container">
              <div class="changesize-box">
                <img
                  v-for="(img, index) in imgEditorList"
                  :key="img.id"
                  :src="img.url"
                  alt=""
                  :style="{
                    width: img.imgSize.width + 'px',
                    height: img.imgSize.height + 'px'
                  }"
                  v-show="curImg == index"
                />
              </div>
              <div class="reset-btn" @click="resetSize">
                <el-button size="">撤销</el-button>
              </div>
            </div>
            <div class="bottom-tool-btn">
              <div class="check-btn" @click="checkChangeSize">
                <el-button type="primary" size="">修改</el-button>
              </div>
              <div class="changesize-input">
                <div class="img-width">
                  <span>宽：</span>
                  <el-input v-model="imgSize.width" @input="handleWidth"></el-input>
                </div>
                <div class="lock" @click="toggleLock">
                  <el-icon v-if="!isLock">
                    <Unlock />
                  </el-icon>
                  <el-icon class="lock-ico" v-else>
                    <Lock />
                  </el-icon>
                </div>
                <div class="img-height">
                  <span>高：</span>
                  <el-input v-model="imgSize.height" @input="handleHeight"></el-input>
                </div>
                <span>像素（px）</span>
              </div>
            </div>
          </div>
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <div class="right-btn">
            <el-button type="primary" @click="replaceImg">{{ isSingleEdit ? '应用' : '全部应用' }}</el-button>
            <el-button @click="showImgEditor = false">关闭</el-button>
          </div>
        </span>
      </template>
    </el-dialog>
    <!-- <ImageUpload v-if="showModuleAxupImgs" v-model:showDialog="showModuleAxupImgs" :limit="1" @getImage="insertModuleImage" :isToJpg="true" allow=".jpg,.jpeg,.gif,.bmp,.png,.ico"></ImageUpload> -->
    <FilesUpload v-if="showModuleAxupImgs" v-model:showDialog="showModuleAxupImgs" :limit="1" @getFileList="insertModuleImage" allow=".jpg,.jpeg,.gif,.bmp,.png,.ico" :isToJpg="true"></FilesUpload>
  </div>
</template>

<script setup>
/* eslint-disable */
import { ref, reactive, computed, onMounted, nextTick, watch } from 'vue'
import { Unlock, Lock, Close } from '@element-plus/icons-vue'
import { transBase64FromImage, getRandomString } from '@/utils/tools'
import { singleUpload } from '@/utils/upload'
import { useStore } from 'vuex'
import { FilesUpload } from '@ruifox-cms/components'

const props = defineProps({
  show: {
    type: Boolean,
    default: false
  },
  isSingleEdit: {
    type: Boolean,
    default: false
  },
  imgEditorList: {
    type: Array,
    default: () => []
  },
  editorImages: {
    type: Array,
    default: () => []
  },
  currentImg: {
    type: Object,
    default: () => {}
  },
  tinymce: {
    type: Object,
    default: () => {}
  }
})

const emit = defineEmits(['update:show'])
const store = useStore()
const showImgEditor = computed({
  get() {
    return props.show
  },
  set(val) {
    emit('update:show', val)
  }
})
const singleActionUrl = computed(() => store.state.content.singleActionUrl)
const isSingleEdit = computed(() => props.isSingleEdit)
const imgEditorList = computed(() => props.imgEditorList)
const editorImages = computed(() => props.editorImages)
const currentImg = computed(() => props.currentImg)
const tinymce = computed(() => props.tinymce)
watch(tinymce, (newVal) => {
  console.log(newVal, 333333)
},{deep: true, immediate: true})
const curEditorImg = reactive(Object.assign({}, props.imgEditorList[0]))
const imgSize = reactive(Object.assign({width: 0, height: 0}, curEditorImg.imgSize))
const showModuleAxupImgs = ref(false) // 更换图片
/*********************************************左侧编辑列表*****************************/
const picPosition = ref(1)
const picPositionOptions = ref([
  { label: '居左', value: 1 },
  { label: '居中', value: 2 },
  { label: '居右', value: 3 }
])
const showImgOption = ref(false)
const isLock = ref(true)
const toggleLock = async () => {
  isLock.value = !isLock.value
  if (isLock.value) {
    let res = await getImgSize(curEditorImg.url)
    if (imgSize.width) {
      imgSize.height = Math.round(imgSize.width / (res.width / res.height))
    } else if (imgSize.height) {
      imgSize.width = Math.round(imgSize.height * (res.width / res.height))
    }
  }
}
const rateChangeText = ref('width')
const handleWidth = () => {
  if (isLock.value) {
    imgSize.height = Math.round(imgSize.width / (curEditorImg.imgSize.width / curEditorImg.imgSize.height))
    rateChangeText.value = 'width'
  }
}
const handleHeight = () => {
  if (isLock.value) {
    imgSize.width = Math.round(imgSize.height * (curEditorImg.imgSize.width / curEditorImg.imgSize.height))
    rateChangeText.value = 'height'
  }
}
const getImgSize = url => {
  return new Promise(resolve => {
    let imgObj = new Image()
    imgObj.src = url
    imgObj.onload = () => {
      resolve({
        width: imgObj.width,
        height: imgObj.height
      })
    }
  })
}
const curImg = ref(0)
const curTool = ref(0)
const toolList = ref([
  { icon: '', text: '调整尺寸' },
  { icon: '', text: '裁剪' }
])
// 上传替换模板图片
const insertModuleImage = (moduleImg) => {
  imgEditorList.value[curImg.value].url = moduleImg[0].url

  setAvatarBase64(moduleImg[0].url).then((base64) => {
    imgEditorList.value[curImg.value].base64Url = base64
  })
}
const cropList = ref([
  { icon: '', text: '1:1', scale: 1 },
  { icon: '', text: '9:16', scale: 2 },
  { icon: '', text: '16:9', scale: 3 },
  { icon: '', text: '3:4', scale: 4 },
  { icon: '', text: '4:3', scale: 5 }
])
const option = reactive({
  img: '',
  size: 1,
  outputType: 'jpg',
  autoCropWidth: 'max',
  autoCropHeight: 'max',
  fixedNumber: [1, 1]
})
const curScale = ref(0)
const cropper = ref()
const changeScale = (index, scale) => {
  curScale.value = index
  switch (scale) {
    case 1:
      option.fixedNumber = [1, 1]
      break
    case 2:
      option.fixedNumber = [9, 16]
      break
    case 3:
      option.fixedNumber = [16, 9]
      break
    case 4:
      option.fixedNumber = [3, 4]
      break
    case 5:
      option.fixedNumber = [4, 3]
      break
  }
  nextTick(() => {
    cropper.value.forEach(item => {
      item.goAutoCrop()
    })
  })
}
const changeImg = (index, img) => {
  if (img.checked) {
    curImg.value = index
    Object.assign(curEditorImg, img)
    Object.assign(imgSize, curEditorImg.imgSize)
    setAvatarBase64(img.url).then(base64 => {
      option.img = base64
    })
  }
}
// 过滤勾选的图片Cropper
const filterCropper = data => {
  data.forEach((item, index) => {
    imgEditorList.value.forEach((item2, index2) => {
      if (index == index2) {
        item.checked = item2.checked
        item.isModuleImg = item2.isModuleImg
      }
    })
  })
}
const leftListChooseAllCheck = ref(false)
const leftListChooseBackCheck = ref(false)
// 批量编辑全选
const leftListChooseAll = val => {
  imgEditorList.value.forEach(item => {
    item.checked = val ? true : false
  })
}
// 批量编辑反选
const leftListChooseBack = () => {
  imgEditorList.value.forEach(item => {
    item.checked = !item.checked
  })
  imgEditorList.value.find((item, firstIndex) => {
    if (item.checked) {
      curImg.value = firstIndex
      return item
    }
  })
}
const checkImg = () => {
  filterCropper(cropper.value)
  cropper.value.forEach((item, index) => {
    if (item.checked) {
      item.getCropBlob(async blob => {
        const { width, height } = item.cropInfo
        let formData = new FormData()
        let _fileName = '裁剪图片' + getRandomString(6) + '.jpg'
        formData.append('name', _fileName)
        formData.append('file', blob)
        formData.append('type', 0)
        formData.append('cropWidth', width)
        formData.append('cropHeight', height)
        formData.append('scaledWidth', width)
        formData.append('scaledHeight', height)
        formData.append('startX', 0)
        formData.append('startY', 0)
        const res = await singleUpload(formData, singleActionUrl.value)
        if (res.code === 20000) {
          imgEditorList.value[index].url = res.data.url
          setAvatarBase64(res.data.url).then(base64 => {
            imgEditorList.value[index].base64Url = base64
          })
        }
      })
    }
  })
}
const resetCrop = () => {
  imgEditorList.value[curImg.value].url = editorImages.value[curImg.value].url
  setAvatarBase64(imgEditorList.value[curImg.value].url).then(base64 => {
    option.img = base64
  })
  imgEditorList.value.forEach((item, index) => {
    item.url = editorImages.value[index].url
    setAvatarBase64(item.url).then(base64 => {
      item.base64Url = base64
    })
  })
}
const resetSize = () => {
  imgEditorList.value.forEach(item => {
    Object.assign(item.imgSize, item.oldImgSize)
  })
  Object.assign(imgSize, curEditorImg.imgSize)
}
const deleteImg = index => {
  curImg.value--
  if (curImg.value < 0) {
    curImg.value = 0
  }
  setAvatarBase64(imgEditorList.value[curImg.value].url).then(base64 => {
    option.img = base64
  })
  imgEditorList.value.splice(index, 1)
  editorImages.value.splice(index, 1)
}
const positionObj = {
  1: {
    display: 'block',
    'margin-left': '0',
    'margin-right': 'auto'
  },
  2: {
    display: 'block',
    margin: 'auto'
  },
  3: {
    display: 'block',
    'margin-left': 'auto',
    'margin-right': '0'
  }
}
const replaceImg = () => {
  // 批量
  if (!isSingleEdit.value) {
    let imgList = []
    imgList = tinymce.value.activeEditor.dom.select('img')
    tinymce.value.activeEditor.undoManager.transact(() => {
      imgList.forEach((item, index) => {
        imgEditorList.value.forEach((img, imgIndex) => {
          if (img.checked) {
            // 模板图片不允许修改宽高
            if (item.src == img.oldUrl && index == imgIndex) {
              if (!img.isModuleImg) {
                let width = Number(img.imgSize.width)
                let height = Number(img.imgSize.height)
                item.width = width
                item.height = height
                tinymce.value.activeEditor.dom.setStyles(item, { width: width, height: 'auto', ...positionObj[picPosition.value] })
              }
              item.src = img.url
              tinymce.value.activeEditor.dom.setAttribs(item, { src: img.url })
            }
          }
        })
      })
    })
  } else {
    // 单图
    tinymce.value.activeEditor.undoManager.transact(() => {
      imgEditorList.value.forEach(img => {
        if (currentImg.value.src == img.oldUrl) {
          let width = Number(img.imgSize.width)
          let height = Number(img.imgSize.height)
          currentImg.value.src = img.url
          currentImg.value.width = width
          currentImg.value.height = height
          tinymce.value.activeEditor.dom.setStyles(currentImg.value, { width: width, height: 'auto', ...positionObj[picPosition.value] })
          tinymce.value.activeEditor.dom.setAttribs(currentImg.value, { src: img.url })
        }
      })
    })
  }

  showImgEditor.value = false
}
const checkChangeSize = () => {
  imgEditorList.value.forEach((item, index) => {
    if (item.checked && !item.isModuleImg) {
      let rate = item.oldImgSize.width / item.oldImgSize.height
      if (rateChangeText.value == 'width') {
        item.imgSize.width = imgSize.width
        item.imgSize.height = Math.round(imgSize.width / rate)
      } else {
        item.imgSize.height = imgSize.height
        item.imgSize.width = Math.round(imgSize.width * rate)
      }
    }
  })
}
function base64ToBlob(base64, type) {
  const binStr = atob(base64.split(',')[1])
  const len = binStr.length
  const arr = new Uint8Array(len)
  for (let i = 0; i < len; i++) {
    arr[i] = binStr.charCodeAt(i)
  }
  return new Blob([arr], { type })
}

const changeTool = index => {
  curTool.value = index
}
const setAvatarBase64 = (src, width, height) => {
  return new Promise(resolve => {
    let image = new Image()
    // 处理缓存
    image.src = src + '?v=' + Math.random()
    // 支持跨域图片
    image.crossOrigin = '*'
    if (width) image.width = width
    if (height) image.height = height
    image.onload = () => {
      let base64 = transBase64FromImage(image)
      resolve(base64)
    }
  })
}

onMounted(() => {
  // const keys = Object.keys(imgEditorList.value)
  // changeImg(0, imgEditorList.value[keys[0]])
})
</script>

<style lang="scss" scoped>
.img-editor-dialog {
  .my-header {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
  }
  .img-editor-container {
    height: 100%;
    display: flex;
    .left-list {
      border-right: 1px solid #e4e4e4;
      padding: 20px;
      padding-top: 10px;
      .el-scrollbar__wrap {
        height: 98%;
      }
      .left-list-btns {
        display: flex;
        justify-content: space-around;
        align-items: center;
      }
      ul {
        padding: 0;
        li {
          width: 200px;
          height: 150px;
          position: relative;
          overflow: hidden;
          border-radius: 4px;
          background-color: var(--el-color-primary-light-9);
          margin-bottom: 20px;
          border: 1px solid transparent;
          &.activeImg {
            border: 1px solid $mainColor;
          }
          img {
            width: 100%;
            height: 100%;
            // object-fit: contain;
          }
          .delete {
            position: absolute;
            right: 0;
            top: 0;
            width: 25px;
            height: 25px;
            display: flex;
            justify-content: center;
            align-items: center;
            color: #fff;
            background-color: rgba(#000, 0.5);
            cursor: pointer;
            i {
              font-size: 18px;
            }
          }
          .left-img-checked {
            position: absolute;
            right: 30px;
            top: 0;
            width: 25px;
            height: 25px;
            display: flex;
            justify-content: center;
            align-items: center;
            color: #fff;
            background-color: rgba(#000, 0.5);
            cursor: pointer;
            i {
              font-size: 18px;
            }
          }
          .left-img-index {
            position: absolute;
            left: 0px;
            top: 0;
            width: 20px;
            height: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
            color: #fff;
            background-color: rgba(#000, 0.5);
            cursor: pointer;
          }
        }
      }
    }
    .tool-list {
      border-right: 1px solid #e4e4e4;
      padding: 20px;
      .tool-btn {
        width: 130px;
        height: 30px;
        border-radius: 4px;
        background-color: var(--el-color-primary-light-9);
        color: #333;
        box-sizing: border-box;
        display: flex;
        justify-content: center;
        align-items: center;
        margin-bottom: 10px;
        cursor: pointer;
        i {
          margin-right: 10px;
        }
        &.activeTool {
          background-color: $mainColor;
          color: #fff;
        }
      }
    }
    .right-img-box {
      flex: 1;
      padding: 20px;
      .cropper-container,
      .changesize-container {
        .img-container {
          .cropper-img-box {
            /* width: 468px; */
            height: 600px;
            position: relative;
            .cropper {
              height: 600px;
              position: absolute;
              width: 100%;
              .cropper-box-canvas {
                max-width: 100%;
                max-height: 100%;
              }
            }
          }
          .reset-btn {
            width: 30px;
            height: 30px;
            margin: 10px;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
            i {
              font-size: 18px;
            }
          }
        }
        .bottom-tool-btn {
          position: relative;
          //   height: 80px;
          height: 22px;
          .check-btn {
            position: absolute;
            right: 0px;
            top: -3px;
            width: 30px;
            height: 30px;
            background-color: $mainColor;
            color: #fff;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
            i {
              font-size: 18px;
            }
          }
          ul {
            display: flex;
            justify-content: center;
            padding: 0;
            height: 100%;
            align-items: center;
            li {
              margin: 0 10px;
              cursor: pointer;
              .tool-name {
                font-size: 18px;
              }
              &.activeScale {
                .tool-name {
                  color: $mainColor;
                }
              }
            }
          }
        }
      }
      .changesize-container {
        .img-container {
          .changesize-box {
            height: 600px;
            background-color: var(--el-color-primary-light-9);
            display: flex;
            justify-content: center;
            align-items: center;
            img {
              max-width: 100%;
              max-height: 100%;
              // object-fit: contain;
            }
          }
        }
        .changesize-input {
          height: 100%;
          display: flex;
          align-items: center;
          justify-content: center;
          .img-width,
          .img-height {
            display: flex;
            align-items: center;
            margin: 0 10px;
          }
          .lock {
            cursor: pointer;
            .lock-ico {
              color: red;
            }
          }
        }
      }
    }
  }
  .el-select ::v-deep .el-input__inner {
    width: 95px;
    height: 29px;
    padding-left: 50px;
    // text-align: center;
  }
}
::v-deep(.img-editor-dialog) {
  height: 843px;
  .el-dialog__body {
    height: calc(100% - 133.2px);
    padding-top: 0 !important;
    padding-bottom: 0;
  }
}
</style>
